#include "ping.h"


int  setsockopt_int(int fd, int level, int optname, int optval)
{
	return ::setsockopt(fd, level, optname, &optval, sizeof(int));
}
int  setsockopt_1(int fd, int level, int optname)
{
	return setsockopt_int(fd, level, optname, 1);
}
int  setsockopt_SOL_SOCKET_int(int fd, int optname, int optval)
{
	return setsockopt_int(fd, SOL_SOCKET, optname, optval);
}
int  setsockopt_SOL_SOCKET_1(int fd, int optname)
{
	return setsockopt_SOL_SOCKET_int(fd, optname, 1);
}

int  setsockopt_broadcast(int fd)
{
	return setsockopt_SOL_SOCKET_1(fd, SO_BROADCAST);
}


bool GetIPV4Gateway(const char * pNICName, char *pGateway, unsigned long len)  
{  
    char buffer[200] = { 0 };  
    unsigned long bufLen = sizeof(buffer);  
  
    unsigned long defaultRoutePara[4] = { 0 };  
    FILE * pfd = fopen("/proc/net/route", "r");  
    if (NULL == pfd)  
    {  
        return false;  
    }  
  
    while(fgets(buffer, bufLen, pfd))  
    {  
        sscanf(buffer, "%*s %x %x %x %*x %*x %*x %x %*x %*x %*x\n", (unsigned int *)&defaultRoutePara[1], (unsigned int *)&defaultRoutePara[0], (unsigned int *)&defaultRoutePara[3], (unsigned int *)&defaultRoutePara[2]);  
  
        if (NULL != strstr(buffer, pNICName))  
        {  
            //如果FLAG标志中有 RTF_GATEWAY  
            if (defaultRoutePara[3] & RTF_GATEWAY)  
            {  
                unsigned long ip = defaultRoutePara[0];  
                snprintf(pGateway, len, "%lu.%lu.%lu.%lu", (ip & 0xff), (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff);  
                break;  
            }  
        }  
  
        memset(buffer, 0, bufLen);  
    }  
  
    fclose(pfd);  
    pfd = NULL;  
    return true;  
}


#if 0
ReadThread::ReadThread(QWidget *parent) :QThread(parent)
{
	qDebug("ReadThread");

	alive = true;
	
	
	

}


ReadThread::~ReadThread()
{
	qDebug("~ReadThread");


}

void ReadThread::run()
{
	char buf[100];
	fd_set read_fd;
	int ret = 0;
	struct timeval tv;

	
	if(access(MAY_FIFO, F_OK))
	{
		qDebug("thread should create fifo");
		mkfifo(MAY_FIFO, 0644);
	}

	fifo = open(MAY_FIFO, O_RDONLY);
	if(fifo < 0)
	{
		perror("open fifo failed");
		return ;
	}



	while(alive)
    {
        ret = 0;
        FD_ZERO(&read_fd);
        FD_SET(fifo, &read_fd);
		tv.tv_usec = 0;  //设置select函数的超时时间
		tv.tv_sec = 1;

		
		
        ret = select(fifo+1, &read_fd, NULL, &read_fd, &tv);
        switch(ret)
        {
            case -1:
  //              fprintf(stderr,"fail to select!\n");

                break;
            case 0:
           
  //         		printf("recv time out\n");
          
                break;
            default:
                {
                #if 0
            		if(access(MAY_FIFO, F_OK))
					{
						qDebug("fifo is broken");
						alive = false;
						break;
					}
		#endif			
					memset(buf, 0, sizeof(buf));
					ret = read(fifo, buf, sizeof(buf));
	//				qDebug("return is 0 ret=%d", ret);

                    if(ret > 1)   						//结束时一瞬间回来很多个空字符(1个字节的,空格还是换行?不清楚),必须过滤掉
                   		emit recvdata(QString(buf));
#if 0
                   	else if(ret < 0)					//ret <= 0时表示出错或者管道破裂,直接退出线程
                   	{
                   		qDebug("read error");
                   		alive = 0;	
                   	}
#endif
                }
                break;
        }



	}





	alive = true;

	qDebug("thread exit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
#endif



PingThread::PingThread(QObject *parent)
{
	pHost = NULL;
	alive = 1;

	clearData();
}

void PingThread::clearData()
{
	
	nRecv = 0;
	nSend = 0;
	
	min = 0;
	avg = 0;
	max = 0;
	mdev = 0;
	
	memset(&FirstSendTime, 0, sizeof(FirstSendTime));
	memset(&LastRecvTime, 0, sizeof(LastRecvTime));
		

}



u_int16_t PingThread::Compute_cksum(struct icmp *pIcmp)
{
	u_int16_t *data = (u_int16_t *)pIcmp;
	int len = pack_size+8;
	u_int32_t sum = 0;
	
	while (len > 1)
	{
		sum += *data++;
		len -= 2;
	}

	
	if (1 == len)
	{
		u_int16_t tmp = *data;
		tmp &= 0xff00;
		sum += tmp;
	}

	while (sum >> 16)
		sum = (sum >> 16) + (sum & 0x0000ffff);
	sum = ~sum;
	
	return sum;
}

void PingThread::SetICMP(u_int16_t seq)
{
	struct icmp *pIcmp;
	struct timeval *pTime;

	memset(SendBuffer, 0 ,sizeof(SendBuffer));
	pIcmp = (struct icmp*)SendBuffer;
	
	/* ���ͺʹ���ֱ�ΪICMP_ECHO,0����������� */
	pIcmp->icmp_type = ICMP_ECHO;
	pIcmp->icmp_code = 0;
	pIcmp->icmp_cksum = 0;		//У���
	pIcmp->icmp_seq = seq;		//���
	pIcmp->icmp_id = getpid();	//ȡ���̺���Ϊ��־
	pTime = (struct timeval *)pIcmp->icmp_data;
	gettimeofday(pTime, NULL);	//���ݶδ�ŷ���ʱ��
	pIcmp->icmp_cksum = Compute_cksum(pIcmp);
	
	if (1 == seq)
		FirstSendTime = *pTime;
}

int PingThread::RecvePacket()
{
	int RecvBytes = 0;
	int addrlen = sizeof(struct sockaddr_in);
	struct timeval RecvTime;
	
	int ret = 0;
	  FD_ZERO(&read_fd);
	  FD_SET(sock_icmp, &read_fd);
	  tv1.tv_usec = 0;  //设置select函数的超时时间为1s
	  tv1.tv_sec = 1;
	  
	  ret = select(sock_icmp+1, &read_fd, NULL, NULL, &tv1);
	  switch(ret)
	  {
		  case -1:
	//		  qDebug("fail to select! ");
			  emit data(QString("select error!!!!!!!"));
			  return -1;
			  
		  case 0:
		
	//		  qDebug("recv time out ");
			  emit data(QString("recv time out"));
			  return 0;
			  
		  default:
			  {
			  	memset(SendBuffer, 0 ,sizeof(SendBuffer));
				if ((RecvBytes = recvfrom(sock_icmp, RecvBuffer, pack_size, 0, (struct sockaddr *)&dest_addr, (socklen_t*)&addrlen)) < 0)
				{
	//				qDebug("recvfrom error");
					emit QString("recvfrom error!!!!!!!");
					return -1;
				}
			  }
			  break;
	  }

	gettimeofday(&RecvTime, NULL);
	LastRecvTime = RecvTime;

	if (unpack(&RecvTime) == -1)
	{
		return -1; 
	}

//	qDebug("nRecv=%d", nRecv);
	nRecv++;
	return 0;
}


void PingThread::SendPacket(int Send)
{
	
	SetICMP(Send);

	FD_ZERO(&write_fd);
	FD_SET(sock_icmp, &write_fd);
	tv2.tv_usec = 0;  				//设置select函数的超时时间为5s
	tv2.tv_sec = 5;
	
	switch(select(sock_icmp+1, NULL, &write_fd, NULL, &tv2))
	{
		case -1:
			emit data(QString("write select error!!!!!!!"));
			return;
		case 0:
			emit data(QString("write time out"));
			  return;
		default:
		{
			if(sendto(sock_icmp, SendBuffer, pack_size, 0, (struct sockaddr *)&dest_addr, sizeof(struct sockaddr_in)) < 0)
			{
				emit(QString("sendto error!!!!"));
				return;
			}

			nSend++;
		}
			break;
	}
	
}

double PingThread::GetRtt(struct timeval *RecvTime, struct timeval *SendTime)
{
	struct timeval sub = *RecvTime;

	if ((sub.tv_usec -= SendTime->tv_usec) < 0)
	{
		--(sub.tv_sec);
		sub.tv_usec += 1000000;
	}
	sub.tv_sec -= SendTime->tv_sec;
	
	return sub.tv_sec * 1000.0 + sub.tv_usec / 1000.0; 
}

int PingThread::unpack(struct timeval *RecvTime)
{
	struct ip *Ip = (struct ip *)RecvBuffer;
	struct icmp *Icmp;
	int ipHeadLen;
	double rtt;

	ipHeadLen = Ip->ip_hl << 2; 
	Icmp = (struct icmp *)(RecvBuffer + ipHeadLen);

	 
	if ((Icmp->icmp_type == ICMP_ECHOREPLY) && Icmp->icmp_id == getpid())
	{
		struct timeval *SendTime = (struct timeval *)Icmp->icmp_data;
		rtt = GetRtt(RecvTime, SendTime);
			
//		printf("%u bytes from %s: icmp_seq=%u ttl=%u time=%.1f ms\n", ntohs(Ip->ip_len) - ipHeadLen, inet_ntoa(Ip->ip_src), Icmp->icmp_seq, Ip->ip_ttl, rtt);

		emit data(QString("%1 bytes from %2: icmp_seq=%3 ttl=%4 time=%5 ms").arg(ntohs(Ip->ip_len) - ipHeadLen).arg(inet_ntoa(Ip->ip_src)).arg(Icmp->icmp_seq).arg(Ip->ip_ttl).arg(rtt));
		
		if (rtt < min || 0 == min)
			min = rtt;
		if (rtt > max)
			max = rtt;
		avg += rtt;
		mdev += rtt * rtt;
		
		return 0;
	}

		emit data(QString("packet broken"));
	return -1;
}


void PingThread::Statistics()
{
	double tmp;
    double total_pack;
    double loss_pack;

	total_pack = nSend;
	loss_pack = nSend - nRecv;

	

	alive = 0;
	
	avg /= nRecv;
	tmp = mdev / nRecv - avg * avg;
	mdev = sqrt(tmp);
	
	if (NULL != pHost){
//		printf("--- %s  ping statistics ---\n", pHost->h_name);
		emit data(QString("--- %1  ping statistics ---").arg(pHost->h_name));
	}
	else{
//		printf("--- %s  ping statistics ---\n", IP);
		emit data(QString("--- %1  ping statistics ---").arg(IP));

	}
		

	emit data(QString("%1 packets transmitted, %2 received, %3% packet loss, time %4ms").arg(nSend).arg(nRecv).arg(loss_pack * 100 / total_pack).arg((int)GetRtt(&LastRecvTime, &FirstSendTime)));
	emit data(QString("rtt min/avg/max/mdev = %1/%2/%3/%4 ms").arg(min).arg(avg).arg(max).arg(mdev));
	emit data(QString("发送=%1; 接收=%2; 丢包量=%3; 丢包率=%4% 总时间=%5ms").arg(nSend).arg(nRecv).arg(nSend - nRecv).arg(loss_pack * 100 / total_pack).arg((int)GetRtt(&LastRecvTime, &FirstSendTime)));
	
	
}








void PingThread::setParam(QString ip, QString interval, QString size)
{


	IP = ip;
	pack_size = size.toInt();
	tv.tv_sec  = interval.toInt() / 1000;
	tv.tv_usec = (interval.toInt() % 1000) * 1000;	 
	
	qDebug("pack_size=%d tv_sec=%ld tv_usec=%ld\n", pack_size, tv.tv_sec, tv.tv_usec);
	qDebug() << IP;
	
	

}


void PingThread::run()
{
	qDebug("run start");
	struct timeval tv_set;

	int send_buf = 512*1024;


	struct protoent *protocol;
	 
	if ((protocol = getprotobyname("icmp")) == NULL)
	{
		qDebug("getprotobyname error");
		return;
	}

	qDebug("protocol->p_proto=%d", protocol->p_proto);
	
	if ((sock_icmp = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0)
	{
		qDebug("create socket error!!!!!!");
		return ;
	}

	dest_addr.sin_family = AF_INET;

	if ((inaddr = inet_addr(IP.toLocal8Bit().data())) == INADDR_NONE)
	{
	 if ((pHost = gethostbyname(IP.toLocal8Bit().data())) == NULL)
	 {
		 qDebug("gethostbyname failed!!!!!!!!");
		 return ;
	 }
	 memmove(&dest_addr.sin_addr, pHost->h_addr_list[0], pHost->h_length);
	}
	else
	{
	 memmove(&dest_addr.sin_addr, &inaddr, sizeof(struct in_addr));
	}


	if (NULL != pHost)
	{
		qDebug("PING %s", pHost->h_name);
	}
	else{
	 qDebug("PING %s", IP.toLocal8Bit().data());
	}
	qDebug("(%s) %d bytes of data.\n", inet_ntoa(dest_addr.sin_addr), pack_size);

//	setsockopt_broadcast(sock_icmp);

	if(setsockopt(sock_icmp, SOL_SOCKET, SO_SNDBUF, &send_buf, sizeof(send_buf))) 	//增大发送缓冲到128k
	{
	  perror("set param failed");
	  return ;
	}

//	setsockopt_int(sock_icmp, IPPROTO_IP, IP_TTL, 32);
		/* above doesn't affect packets sent to bcast IP, so... */
//	setsockopt_int(sock_icmp, IPPROTO_IP, IP_MULTICAST_TTL, 32);
	setsockopt_SOL_SOCKET_int(sock_icmp, SO_RCVBUF, send_buf);

	qDebug("pack_size=%d tv_sec=%ld tv_usec=%ld\n", pack_size, tv.tv_sec, tv.tv_usec);


	while (alive)
	{
	//	int unpack_ret;

		tv_set = tv;
		
		SendPacket(nSend);
		
		RecvePacket();
		
		emit info(nSend, nRecv);
		select(0, NULL, NULL, NULL, &tv_set); //use for delay....

	}
	
	Statistics();	


	alive = true;

	


}




PingTool::PingTool(QWidget *parent) : QDialog(parent)
{
	qDebug("new PingTool\n");

	totalTime.setHMS(0, 0, 0); // hh:mm:ss
	

	im = new InputMethod;
	process = new QProcess(this);
	thread	= new PingThread(this);

	QGroupBox 	*mode_grpbox;
	QGroupBox 	*ipaddr_grpbox;
	QGroupBox 	*param_grpbox;

	QGroupBox 	*info_grpbox;
	
	tickTimer = new QTimer(this);
	barTimer  = new QTimer(this);


	QLabel *ip_label = new QLabel;
	QLabel *send_label = new QLabel;
	QLabel *loss_label = new QLabel;
	QLabel *loss_percent_label = new QLabel;
	QLabel *start_time_label = new QLabel;
	QLabel *end_time_label = new QLabel;
	QLabel *total_time_label = new QLabel;
	QLabel *count_label = new QLabel;
	QLabel *period_label = new QLabel;
	QLabel *packsize_label = new QLabel;
	
	QLabel *send_pack_lb = new QLabel(this);
	QLabel *loss_pack_lb = new QLabel(this);
	QLabel *loss_percent_lb = new QLabel(this);
	QLabel *total_time_lb = new QLabel(this);

	send_pack_lb	->setText(tr("发送量"));
	loss_pack_lb 	->setText(tr("丢包量"));
	loss_percent_lb ->setText(tr("丢包率"));
	total_time_lb 	->setText(tr("计时"));

	QGridLayout 	*pMainLayout			= new QGridLayout;
	QHBoxLayout     *pIpLayout       		= new QHBoxLayout;
	QGridLayout 	*pModeLayout			= new QGridLayout;
	QGridLayout 	*pParamLayout			= new QGridLayout;
	QVBoxLayout 	*pButtonLayout	   		= new QVBoxLayout;
	QHBoxLayout 	*infoLayout				= new QHBoxLayout;

	typeCombo		= new QComboBox(this);	
	unitCombo		= new QComboBox;
	timingRadioBut = new QRadioButton;
	rationRadioBut = new QRadioButton;
	
	start_bt = new QPushButton;
	stop_bt = new QPushButton;
	one_key_getip_bt = new QPushButton;
	exit_bt = new QPushButton;
	read_log_bt = new QPushButton;
	set_log_path = new QPushButton;
	
	
	mode_grpbox 		= new QGroupBox;
	ipaddr_grpbox		= new QGroupBox;
	param_grpbox		= new QGroupBox;
	info_grpbox         = new QGroupBox(this);

	ip_edit			= new QLineEdit;
	timing_edit		= new QLineEdit;
	count_edit		= new QLineEdit;
	period_edit		= new QLineEdit;
	pack_size_edit	= new QLineEdit;
	debug_edit		= new QPlainTextEdit;

	send_pack_edit 		= new QLineEdit(this);
	loss_pack_edit 		= new QLineEdit(this);
	loss_persent_edit 	= new QLineEdit(this);
	total_time_edit 	= new QLineEdit(this);

	send_pack_edit->setReadOnly(true);
	loss_pack_edit->setReadOnly(true);
	loss_persent_edit->setReadOnly(true);
	total_time_edit->setReadOnly(true);

	if(g_lcdsize == LCDSIZE_480x272)
	{
		ipaddr_grpbox->setTitle(tr("地址设置"));
		mode_grpbox->setTitle(tr("模式设置"));
		param_grpbox->setTitle(tr("参数设置"));
		info_grpbox->hide();

		ip_label->setText("目标地址:");
		count_label->setText("次");

		send_label->setText("发送量(包):");
		loss_label->setText("丢包量(包):");
		loss_percent_label->setText("丢包率    :");

		start_time_label->setText("开始时间:");
		end_time_label->  setText("结束时间:");
		total_time_label->setText("总时间  :");

		timingRadioBut->setText(tr("定时"));
		rationRadioBut->setText(tr("定量"));

		period_label->setText("周期(ms):");
		packsize_label->setText("包(字节):");

		start_bt->setText("开始测试");
		stop_bt->setText("停止测试");
		one_key_getip_bt->setText("一键动态IP");
		exit_bt->setText("退出");
		read_log_bt->setText("查看日志");
		set_log_path->setText("保存日志");


	}else{
		ipaddr_grpbox->setTitle(tr("地址设置"));
		mode_grpbox->setTitle(tr("模式设置"));
		param_grpbox->setTitle(tr("参数设置"));
		info_grpbox->setTitle(tr("实时信息"));

		ip_label->setText("目标地址:");
		count_label->setText("次");
		
		send_label->setText("发送量(包):");
		loss_label->setText("丢包量(包):");
		loss_percent_label->setText("丢包率    :");

		start_time_label->setText("开始时间:");
		end_time_label->  setText("结束时间:");
		total_time_label->setText("总时间  :");

		timingRadioBut->setText(tr("定时模式"));
		rationRadioBut->setText(tr("定量模式"));

		period_label->setText("发送周期(ms):");
		packsize_label->setText("包大小(字节):");

		start_bt->setText("开始测试");
		stop_bt->setText("停止测试");
		one_key_getip_bt->setText("一键动态IP");
		exit_bt->setText("退出");
		read_log_bt->setText("查看日志");
		set_log_path->setText("保存日志");


	}




	stop_bt->setEnabled(false);
	timingRadioBut->setChecked(true);

	QList<QString> unitList;
	QList<QString> typeList;

	unitList	<< "sec"
				<< "min"
				<< "hour"
				<< "day";

	typeList	<< "有线网"
				<< "WIFI";
	
		
	typeCombo->addItems(typeList);
	typeCombo->setView(new QListView());
	typeCombo->setCurrentIndex(0);

	unitCombo->addItems(unitList);
	unitCombo->setView(new QListView());
	unitCombo->setCurrentIndex(1);

	debug_edit->setCenterOnScroll(false);   //cursor is always at below
	debug_edit->setMaximumBlockCount(500);    //最大行数

	char gateway[32] = { 0 };  
	GetIPV4Gateway("eth0", gateway, 32);  

	qDebug("gateway: %s", gateway);

	ip_edit->setText(QString(gateway));
	timing_edit->setText("30");
	count_edit->setText("10000");
	period_edit->setText("10");
	pack_size_edit->setText("65500");

	ip_edit->installEventFilter(im);
	ip_edit->setObjectName("ip_edit");
    timing_edit->installEventFilter(im);
    timing_edit->setObjectName("timing_edit");
    count_edit->installEventFilter(im);
    count_edit->setObjectName("count_edit");
    period_edit->installEventFilter(im);
    period_edit->setObjectName("period_edit");
	pack_size_edit->installEventFilter(im);
	pack_size_edit->setObjectName("pack_size_edit");

	infoLayout->addWidget(send_pack_lb);
	infoLayout->addWidget(send_pack_edit);
	infoLayout->addWidget(loss_pack_lb);
	infoLayout->addWidget(loss_pack_edit);
	infoLayout->addWidget(loss_percent_lb);
	infoLayout->addWidget(loss_persent_edit);
	infoLayout->addWidget(total_time_lb);
	infoLayout->addWidget(total_time_edit);



	pIpLayout->addWidget(ip_label);
	pIpLayout->addWidget(ip_edit);
	pIpLayout->addWidget(typeCombo);

	pButtonLayout->addWidget(start_bt);
	pButtonLayout->addWidget(stop_bt);
	pButtonLayout->addWidget(one_key_getip_bt);
	pButtonLayout->addWidget(set_log_path);
	pButtonLayout->addWidget(exit_bt);
	

	pModeLayout->addWidget(timingRadioBut, 0,0,1,1);
	pModeLayout->addWidget(rationRadioBut, 1,0,1,1);
	pModeLayout->addWidget(timing_edit,    0,1,1,1);
	pModeLayout->addWidget(count_edit,     1,1,1,1);
	pModeLayout->addWidget(unitCombo,      0,2,1,1);
	pModeLayout->addWidget(count_label,    1,2,1,1);

	pParamLayout->addWidget(period_label, 		0,0,1,1);
	pParamLayout->addWidget(packsize_label, 	1,0,1,1);
	pParamLayout->addWidget(period_edit, 		0,1,1,1);
	pParamLayout->addWidget(pack_size_edit, 	1,1,1,1);


	ipaddr_grpbox->setLayout(pIpLayout);
	mode_grpbox->setLayout(pModeLayout);
	param_grpbox->setLayout(pParamLayout);
	info_grpbox->setLayout(infoLayout);

	

	pMainLayout->addWidget(ipaddr_grpbox,		0,0,1,2);
	pMainLayout->addWidget(mode_grpbox,			1,0,1,1);
	pMainLayout->addWidget(param_grpbox,		1,1,1,1);


	if(g_lcdsize != LCDSIZE_480x272)
		pMainLayout->addWidget(info_grpbox,			2,0,1,2);

	pMainLayout->addWidget(debug_edit,			3,0,1,2);
	pMainLayout->addLayout(pButtonLayout,		1,3,3,1);
		

	connect(im, SIGNAL(setImObjName(QString)), this, SLOT(createImConnect(QString)));
	connect(start_bt, 			SIGNAL(clicked()), this, SLOT(start_ping_test()));
	connect(exit_bt, 			SIGNAL(clicked()), this, SLOT(exit_ping_test()));
	connect(one_key_getip_bt, 	SIGNAL(clicked()), this, SLOT(one_key_getip()));
	connect(set_log_path, 	SIGNAL(clicked()), this, SLOT(setLogPath()));
	connect(stop_bt, 			SIGNAL(clicked()), this, SLOT(stop_ping_test()));
	connect(read_log_bt, 		SIGNAL(clicked()), this, SLOT(read_ping_log()));
	connect(timingRadioBut,		SIGNAL(clicked()), this, SLOT(ping_mode_timing()));
	connect(rationRadioBut,		SIGNAL(clicked()), this, SLOT(ping_mode_ration()));
	connect(tickTimer,			SIGNAL(timeout()), this ,SLOT(stop_ping_test()));
	connect(barTimer,			SIGNAL(timeout()), this ,SLOT(auto_draw_bar()));
	connect(typeCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(comboBoxValueChanged()));

	

	connect(thread, SIGNAL(data(QString)), this, SLOT(pingReadOut(QString)));
	connect(thread, SIGNAL(info(long, long)), this, SLOT(pinginfo(long, long)));

	ping_mode_timing();
	
	this->setLayout(pMainLayout);

}

PingTool::~PingTool()
{

	qDebug("pingtool exit");



	

	thread->alive = false;
	delete thread;


}



void PingTool::debug_add_warning(const char *str)
{	
	debug_edit->setStyleSheet("QPlainTextEdit{color:red}");

	debug_edit->appendPlainText(QString(str)); 
	debug_edit->setStyleSheet("QPlainTextEdit{color:black}");
}


void PingTool::debug_add_text(const char *str)
{	
	debug_edit->appendPlainText(QString(str)); 
}


void PingTool::debug_add_text(QString str)
{
	debug_edit->appendPlainText(str); 
}

void PingTool::pingReadOut(QString data)
{

	debug_edit->appendPlainText(data); 
}

void PingTool::pinginfo(long send, long recv)
{
	
	send_pack_edit->setText(QString::number(send));
	loss_pack_edit->setText(QString::number(send-recv));
	loss_persent_edit->setText(QString::number((send-recv) * 100 / send) + "%");
	
}



bool PingTool::check_ping_vaile()
{
	unsigned int inaddr = 1;
	struct hostent* host = NULL;

	QByteArray tmp = unitCombo->currentText().toUtf8();
    char *pName = const_cast<char*>(tmp.data());

	qDebug("unit=%s", pName);
	

	if(!isDigitStr(timing_edit->text()) || !isDigitStr(period_edit->text()) || !isDigitStr(pack_size_edit->text()))
	{
		qDebug("edit is not a num!");

		debug_add_warning("发送时间,发送周期,包大小必须是数字!");

		return false;
	}


	//int rage: ~2147483647 - 2147483647 
	if(timingRadioBut->isChecked())
	{
		mode = unitCombo->currentIndex();
		qDebug("timing is enable mode=%d", mode);
		switch(mode)
		{
			case 0:   //second
				unit = 1;
				break;
			case 1:   //minute  
				unit = 60;
				break;
			case 2:   //hour 
				unit = 3600;
				break;
			case 3:   //day 
				unit = 86400;
				break;	
			case 4:
				unit = 0;
				break;
			
		}

		timing = timing_edit->text().toInt() * unit;
		qDebug("timing=%d", timing);

		if((timing*1000)>2147483647 || timing<0)
		{
			qDebug("timing is out of int range!");

			debug_add_warning("定时时间超出整形数范围!");
			return false;

		}
	

		QStringList tmp = ip_edit->text().split('.');

		qDebug("len=%d", tmp.length());

		if(tmp.length() != 4){
			debug_add_warning("IP地址不正确!");
			return false;
		}
		
		inaddr = inet_addr(ip_edit->text().toLocal8Bit().data());
		if(inaddr == INADDR_NONE)	//判断用户输入的是否为IP地址还是域名
		{
			
			host = gethostbyname(ip_edit->text().toLocal8Bit().data());	//输入的是域名地址
			if(host == NULL)
			{
				printf("Fail to gethostbyname!\n");
				debug_add_warning("IP地址不正确!");
				return false;
			}
		}

	}else if(rationRadioBut->isChecked()){

		count = count_edit->text().toInt();

		qDebug("ration is enable count=%d", count);
	}


	thread->setParam(ip_edit->text(), period_edit->text(), pack_size_edit->text());

	return true;

}


void PingTool::one_key_getip()
{
	qDebug("one_key_getip\n");

	system("killall -9 udhcpc &");
	system("udhcpc -b -i eth0 -p /var/run/udhcpd.pid -R");
   
    QFile::remove("/tmp/ping_ip");
    system("ifconfig eth0 > /tmp/ping_ip");

	process->start("sync");
    process->waitForFinished();

	QFile filetmplink("/tmp/ping_ip");
    filetmplink.open(QFile::ReadOnly);

    

	QString stmp =filetmplink.readAll();
    QString stmp2="Mask:";
    QString stmp3="Bcast:";
	
    if(stmp.contains(stmp2) && stmp.contains(stmp3)) {
        QString address;
	
		QList<QHostAddress> list = QNetworkInterface::allAddresses();  
		foreach (QHostAddress tmpaddr, list)  
			 {  
    		if(tmpaddr.protocol() == QAbstractSocket::IPv4Protocol)  
    		{  
        		//自动查找IPv4地址并过滤掉本地地址  
        		if (tmpaddr.toString().contains("127.0."))  
       			{  
            		continue;  
        		}  
        		address = tmpaddr.toString();  
    		}  
		}  

		qDebug()<<"address:"<<address;

     	QMessageBox::information(NULL, tr("提示"), QString("获取动态IP成功: %1").arg(address));
    

	
	}else{

		QMessageBox::information(NULL, tr("错误"), tr("获取动态IP失败"));
	}





	
	qDebug("one_key_getip end\n");
}

void PingTool::exit_ping_test()
{


	thread->alive = false;


	this->close();
}

void PingTool::read_ping_log()
{
	QDialog *log_dialog = new QDialog;
	QTextEdit *log_edit = new QTextEdit;
	QPushButton *exit_log_bt = new QPushButton;
	qDebug("read_ping_log");
	
	connect(exit_log_bt, SIGNAL(clicked()), log_dialog, SLOT(close()));
	

	QGridLayout *tmplayout = new QGridLayout;
	exit_log_bt->setText("退出");

	tmplayout->addWidget(log_edit, 	0,0,2,1);
	tmplayout->addWidget(exit_log_bt, 	2,0,1,1);
	log_dialog->setLayout(tmplayout);

	log_edit->setReadOnly(true);

	log_dialog->setModal(true);
	log_dialog->showFullScreen();

	QFile file(log_path);
	if(!file.open(QFile::ReadOnly))
	{
			QMessageBox::information(NULL, tr("警告"), tr("打开日志文件失败"));
			log_dialog->close();
	}else{
		log_edit->append(file.readAll());
	}


}

void PingTool::ping_mode_ration()
{
#if 0	
	timing_edit->setEnabled(false);
	unitCombo->setEnabled(false);
	count_edit->setEnabled(true);	
#else

	QMessageBox::information(NULL, tr("德玛西亚!"), tr("暂不支持定量功能"));
	timingRadioBut->setChecked(true);
	ping_mode_timing();
#endif

	
}

void PingTool::ping_mode_timing()
{
	timing_edit->setEnabled(true);
	unitCombo->setEnabled(true);
	count_edit->setEnabled(false);

}

void PingTool::pingreceiveData(const QString str)
{
	debug_add_text(str);
}

void PingTool::createImConnect(QString ObjName)
{
	disconnect(im->keyboard, SIGNAL(setvalue(QString)), ip_edit, SLOT(setText(QString)));
	disconnect(im->keyboard, SIGNAL(setvalue(QString)), timing_edit, SLOT(setText(QString)));
	disconnect(im->keyboard, SIGNAL(setvalue(QString)), count_edit, SLOT(setText(QString)));
	disconnect(im->keyboard, SIGNAL(setvalue(QString)), period_edit, SLOT(setText(QString)));
	disconnect(im->keyboard, SIGNAL(setvalue(QString)), pack_size_edit, SLOT(setText(QString)));


	if(ObjName=="ip_edit")
	   connect(im->keyboard,SIGNAL(setvalue(QString)), ip_edit, SLOT(setText(QString)));
	if(ObjName=="timing_edit")
	   connect(im->keyboard,SIGNAL(setvalue(QString)), timing_edit, SLOT(setText(QString)));
	if(ObjName=="count_edit")
	   connect(im->keyboard,SIGNAL(setvalue(QString)), count_edit, SLOT(setText(QString)));
	if(ObjName=="period_edit")
	   connect(im->keyboard,SIGNAL(setvalue(QString)), period_edit, SLOT(setText(QString)));
	if(ObjName=="pack_size_edit")
	   connect(im->keyboard,SIGNAL(setvalue(QString)), pack_size_edit, SLOT(setText(QString)));



}

void PingTool::auto_draw_bar(void)
{
	totalTime = totalTime.addSecs(1);
	total_time_edit->setText(totalTime.toString("hh:mm:ss"));
}

void PingTool::setLogPath(void)
{

	log_path = QFileDialog::getExistingDirectory(this, tr("选择日志保存的文件夹"), "/", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);

	log_path += "/ping.txt";

	if(QFile::exists(log_path))
    {
		qDebug("log is exist");
		QFile::remove(log_path);
    }

	qDebug() << log_path;

	QFile file(log_path);

    if(!file.open(QFile::WriteOnly | QFile::Truncate))  
    {
    	qDebug("open error");	
    	return ;
    }

	/* read the /tmp/sd_usb_test and get time */
	QTextStream txtInput(&file);  
	
	txtInput << debug_edit->toPlainText();

	file.flush();
	file.close(); 

	system("sync &");
	
	do{
			;
	}while(get_file_size(log_path.toLocal8Bit().data()) <= 0);

	
	debug_add_text(QString("日志已保存到:%1(日志不包含此条信息)").arg(log_path));
}

void PingTool::comboBoxValueChanged(void)
{
	qDebug("net type change");
	char gateway[32] = { 0 };  

	switch(typeCombo->currentIndex())
	{
		case 0:
			GetIPV4Gateway("eth0", gateway, 32);  
			break;
		case 1:
			GetIPV4Gateway("wlan0", gateway, 32);
			break;
	}

	qDebug("gateway: %s", gateway);
	ip_edit->setText(QString(gateway));
}

void PingTool::start_ping_test()
{
	QString cmd;
	qDebug("start_ping_test\n");

	totalTime.setHMS(0, 0, 0);

	debug_edit->clear();
//	debug_add_text("正在检查参数是否合法...");

	if(check_ping_vaile() == false)
	{
//		debug_add_warning("测试失败!");
		return ;
	}


#if 1
	qDebug("period=%d", period_edit->text().toInt());


	thread->clearData();

	if(!thread->isRunning())
	{
		qDebug("thread is not run , restart now");
		thread->start();
	}

#endif

	start_bt->setEnabled(false);
	stop_bt->setEnabled(true);
	one_key_getip_bt->setEnabled(false);
	exit_bt->setEnabled(false);
	unitCombo->setEnabled(false);
	timingRadioBut->setEnabled(false);
	rationRadioBut->setEnabled(false);
	read_log_bt->setEnabled(false);
	set_log_path->setEnabled(false);

	ip_edit->setReadOnly(true);
	timing_edit->setReadOnly(true);
	count_edit->setReadOnly(true);
	period_edit->setReadOnly(true);
	pack_size_edit->setReadOnly(true);

	tickTimer->start(timing * 1000);
	barTimer->start(1000);				  


#if 0	
	QDateTime current_date_time = QDateTime::currentDateTime();
	QDateTime datetime;

	
	switch(unitCombo->currentIndex())
	{
		case 0:
			tmp_unit = QString("秒");
			break;
		case 1:
			tmp_unit = QString("分钟");
			break;
		case 2:
			tmp_unit = QString("小时");
			break;
		case 3:
			tmp_unit = QString("天");
			break;

	}
#endif


}


void PingTool::stop_ping_test()
{
	volatile int a;
	QString str;

//	cur_time = 0;

	barTimer->stop();		
	tickTimer->stop();


	QTimer *pTimer = qobject_cast<QTimer *>(sender());
    QPushButton *pBtn = qobject_cast<QPushButton *>(sender());
    if(pTimer == tickTimer) {
        qDebug("stop by tickTimer");  
   //     pProgressBar->setFormat(QString("%1%").arg("100"));
	//	pProgressBar->setValue(100);					

    }else if(pBtn == stop_bt) {
        qDebug("stop by handle");
    }
	

	qDebug("stop_ping_test\n");

	start_bt->setEnabled(true);
	stop_bt->setEnabled(false);
	one_key_getip_bt->setEnabled(true);
	exit_bt->setEnabled(true);
	unitCombo->setEnabled(true);
	timingRadioBut->setEnabled(true);
	rationRadioBut->setEnabled(true);
	read_log_bt->setEnabled(true);
	set_log_path->setEnabled(true);

	ip_edit->setReadOnly(false);
	timing_edit->setReadOnly(false);
	count_edit->setReadOnly(false);
	period_edit->setReadOnly(false);
	pack_size_edit->setReadOnly(false);

	thread->alive = false;





//	qDebug("stop_ping_test end\n");
}



















